package cn.ug.operation.service.impl;

import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.type.ResultType;
import cn.ug.config.RedisGlobalLock;
import cn.ug.core.ensure.Ensure;
import cn.ug.feign.CouponRepertoryService;
import cn.ug.feign.MemberGoldService;
import cn.ug.msg.mq.Msg;
import cn.ug.operation.bean.EverydayGuessStatisticsBean;
import cn.ug.operation.bean.GuessMemberBean;
import cn.ug.operation.bean.GuessMemberStatisticsBean;
import cn.ug.operation.bean.MemberGuessRecordBean;
import cn.ug.operation.mapper.GuessJoinMemberMapper;
import cn.ug.operation.mapper.GuessRecordMapper;
import cn.ug.operation.mapper.GuessShareRecordMapper;
import cn.ug.operation.mapper.entity.GuessJoinMember;
import cn.ug.operation.mapper.entity.GuessRecord;
import cn.ug.operation.mapper.entity.GuessShareRecord;
import cn.ug.operation.service.GuessRecordService;
import cn.ug.pay.bean.type.BillGoldTradeType;
import cn.ug.util.BigDecimalUtil;
import cn.ug.util.UF;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.ug.config.QueueName.QUEUE_MSG_SEND;

@Service
public class GuessRecordServiceImpl implements GuessRecordService {
    @Autowired
    private GuessRecordMapper guessRecordMapper;
    @Autowired
    private CouponRepertoryService couponRepertoryService;
    @Autowired
    private RedisGlobalLock redisGlobalLock;
    @Autowired
    private MemberGoldService memberGoldService;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private GuessJoinMemberMapper guessJoinMemberMapper;
    @Autowired
    private GuessShareRecordMapper guessShareRecordMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public boolean share(String memberId, int activityId, int endPoint) {
        if (StringUtils.isNotBlank(memberId) && activityId > 0) {
            GuessShareRecord record = new GuessShareRecord();
            record.setActivityId(activityId);
            record.setMemberId(memberId);
            record.setAddTime(UF.getFormatDateTime(LocalDateTime.now()));
            int rows = guessShareRecordMapper.insert(record);
            if (rows > 0) {
                boolean result=  false;
                GuessJoinMember joinMember = guessJoinMemberMapper.findJoinInfo(record.getMemberId(), record.getActivityId());
                if (joinMember == null) {
                    joinMember = new GuessJoinMember();
                    joinMember.setActivityId(record.getActivityId());
                    joinMember.setAddTime(UF.getFormatDateTime(LocalDateTime.now()));
                    joinMember.setBalance(1);
                    joinMember.setShareNum(1);
                    joinMember.setLastestTime(UF.getFormatDateTime(LocalDateTime.now()));
                    joinMember.setMemberId(record.getMemberId());
                    result = guessJoinMemberMapper.insert(joinMember) > 0 ? true : false;
                } else {
                    result = guessJoinMemberMapper.updateShareNum(memberId, activityId) > 0 ? true : false;
                }
                String key = "GuessRecordServiceImpl:share:times:" + record.getMemberId()+":"+UF.getFormatDateNow() + ":" + activityId;
                String value = redisTemplate.opsForValue().get(key);
                if (StringUtils.isBlank(value)) {
                    SimpleDateFormat timeFormat = new SimpleDateFormat("HHmm");
                    int currentPoint = Integer.parseInt(timeFormat.format(new Date()));
                    if (currentPoint <= endPoint) {
                        rows = guessJoinMemberMapper.updateBalance(memberId, activityId, 1);
                        if (rows > 0) {
                            redisTemplate.opsForValue().set(key, String.valueOf(1));
                        }
                    }
                }
                return result;
            }
        }
        return false;
    }

    @Override
    public boolean share(GuessRecord record, String couponId, String mobile) {
        String key = "GuessRecordServiceImpl:share:" + record.getMemberId();
        try {
            if(!redisGlobalLock.tryLock(key)) {
                return false;
            }
            if (record == null || record.getId() == 0) {
                return false;
            }
            GuessRecord guessRecord = guessRecordMapper.findById(record.getId());
            if (guessRecord == null || guessRecord.getId() == 0) {
                return false;
            }
            if (guessRecord.getGuessResult() == 1 || guessRecord.getShareStatus() == 2) {
                return false;
            }
            String guessDate = UF.getFormatDate(guessRecord.getGuessTime());
            if (guessRecord.getGuessResult() == 2) {
                double golds = guessRecordMapper.sumSomedayGolds(record.getActivityId(), record.getMemberId(), guessDate);
                if (golds > 0) {
                    Ensure.that(true).isTrue("25000068");
                }
                int tradeType = BillGoldTradeType.ACTIVITY.getValue();
                SerializeObject bean = memberGoldService.investRebate(record.getMemberId(), new BigDecimal(record.getGotGold()), BillGoldTradeType.ACTIVITY.getValue());
                if(bean != null && bean.getCode() == ResultType.NORMAL) {
                    guessJoinMemberMapper.updateGolds(record.getMemberId(), record.getActivityId(), new BigDecimal(record.getGotGold()));
                    guessRecordMapper.updateGotStatus(record.getActivityId(), record.getMemberId(), guessDate, 2);
                    record.setShareStatus(2);
                    record.setGotStatus(2);
                    Msg msg = new Msg();
                    msg.setMemberId(record.getMemberId());
                    msg.setMobile(mobile);
                    msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.GUESS_GOLD_PRICE.getIndex());
                    Map<String, String> paramMap = new HashMap<>();
                    paramMap.put("weight", String.valueOf(record.getGotGold()));
                    msg.setParamMap(paramMap);
                    amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                } else {
                    record.setGotGold(0);
                }
            }
            if (record.getGuessResult() == 3 && StringUtils.isNotBlank(couponId)) {
                SerializeObject bean = couponRepertoryService.giveCoupon(record.getMemberId(), couponId);
                if(bean != null && bean.getCode() == ResultType.NORMAL) {
                    guessJoinMemberMapper.updateCoupons(record.getMemberId(), record.getActivityId(), 1);
                    record.setShareStatus(2);
                    record.setGotStatus(2);
                    Msg msg = new Msg();
                    msg.setMemberId(record.getMemberId());
                    msg.setMobile(mobile);
                    msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.COUPON_NOTIFY.getIndex());
                    Map<String, String> paramMap = new HashMap<>();
                    paramMap.put("activityName", "猜金价活动");
                    paramMap.put("amount", String.valueOf(record.getCouponAmount()));
                    msg.setParamMap(paramMap);
                    amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                } else {
                    record.setCouponAmount(0);
                }
            }
            return guessRecordMapper.update(record) > 0 ? true : false;
        } finally {
            redisGlobalLock.unlock(key);
        }
    }

    @Override
    public List<EverydayGuessStatisticsBean> queryForRecord(int activityId, int offset, int size) {
        if (activityId > 0) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("activityId", activityId);
            params.put("offset", offset);
            params.put("size", size);
            return guessRecordMapper.queryForRecord(params);
        }
        return null;
    }

    @Override
    public int countForRecord(int activityId) {
        if (activityId > 0) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("activityId", activityId);
            return guessRecordMapper.countForRecord(params);
        }
        return 0;
    }

    @Override
    public List<GuessMemberBean> queryForGuessMembers(int activityId, String guessDate, int guessResult, String memberId, String number, int offset, int size) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("activityId", activityId);
        params.put("guessResult", guessResult);
        if (StringUtils.isNotBlank(guessDate)) {
            params.put("guessDate", guessDate);
        }
        if (StringUtils.isNotBlank(memberId)) {
            params.put("memberId", memberId);
        }
        if (StringUtils.isNotBlank(number)) {
            params.put("number", number);
        }
        params.put("offset", offset);
        params.put("size", size);
        return guessRecordMapper.queryForGuessMembers(params);
    }

    @Override
    public int countForGuessMembers(int activityId, String guessDate, int guessResult, String memberId, String number) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("activityId", activityId);
        params.put("guessResult", guessResult);
        if (StringUtils.isNotBlank(guessDate)) {
            params.put("guessDate", guessDate);
        }
        if (StringUtils.isNotBlank(memberId)) {
            params.put("memberId", memberId);
        }
        if (StringUtils.isNotBlank(number)) {
            params.put("number", number);
        }
        return guessRecordMapper.countForGuessMembers(params);
    }

    @Override
    public List<GuessMemberStatisticsBean> queryForGuessMemberStatistics(String name, String mobile, int bindedCard, String startTime, String endTime, int offset, int size) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (StringUtils.isNotBlank(startTime)) {
            params.put("startTime", startTime);
        }
        if (StringUtils.isNotBlank(endTime)) {
            params.put("endTime", endTime);
        }
        if (StringUtils.isNotBlank(mobile)) {
            params.put("mobile", mobile);
        }
        params.put("bindedCard", bindedCard);
        params.put("offset", offset);
        params.put("size", size);
        return guessJoinMemberMapper.queryForList(params);
    }

    @Override
    public int countForGuessMemberStatistics(String name, String mobile, int bindedCard, String startTime, String endTime) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (StringUtils.isNotBlank(startTime)) {
            params.put("startTime", startTime);
        }
        if (StringUtils.isNotBlank(endTime)) {
            params.put("endTime", endTime);
        }
        if (StringUtils.isNotBlank(mobile)) {
            params.put("mobile", mobile);
        }
        params.put("bindedCard", bindedCard);
        return guessJoinMemberMapper.countForCount(params);
    }

    @Override
    public List<MemberGuessRecordBean> queryForListByMemberId(String memberId, int activityId, int offset, int size) {
        if (StringUtils.isNotBlank(memberId)) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("memberId", memberId);
            params.put("activityId", activityId);
            params.put("offset", offset);
            params.put("size", size);
            return guessRecordMapper.queryForListByMemberId(params);
        }
        return null;
    }

    @Override
    public int queryForCountByMemberId(String memberId, int activityId) {
        if (StringUtils.isNotBlank(memberId)) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("memberId", memberId);
            params.put("activityId", activityId);
            return guessRecordMapper.queryForCountByMemberId(params);
        }
        return 0;
    }

    @Override
    public List<MemberGuessRecordBean> queryForListRecent30() {
        return guessRecordMapper.queryForListRecent30();
    }

    @Override
    public Double selectYestodayFinalPrice() {
        return guessRecordMapper.selectYestodayFinalPrice();
    }

    @Override
    public double selectTodayFinalPrice() {
        Double price = guessRecordMapper.selectTodayFinalPrice();
        if (price == null) {
            price = 0D;
        }
        return price;
    }

    @Override
    public MemberGuessRecordBean selectTodayRecord(int activityId, String memberId) {
        if (activityId > 0 && StringUtils.isNotBlank(memberId)) {
            List<MemberGuessRecordBean> beans = guessRecordMapper.selectTodayRecord(activityId, memberId);
            if (beans != null && beans.size() > 0) {
                if (beans.size() > 1) {
                    double gotGold = 0;
                    double couponAmount = 0;
                    MemberGuessRecordBean bean1 = beans.get(0);
                    if (bean1.getGotGold() > 0) {
                        gotGold = bean1.getGotGold();
                    } else if (bean1.getCouponAmount() > 0) {
                        couponAmount = bean1.getCouponAmount();
                    }
                    double data1 = Math.abs(bean1.getGuessPrice() - bean1.getFinalPrice());

                    MemberGuessRecordBean bean2 = beans.get(1);
                    if (gotGold == 0 && bean2.getGotGold() > 0) {
                        gotGold = bean2.getGotGold();
                        couponAmount = 0;
                    }
                    if (gotGold == 0 && couponAmount == 0 && bean2.getCouponAmount() > 0) {
                        couponAmount = bean2.getCouponAmount();
                    }
                    double data2 = Math.abs(bean2.getGuessPrice() - bean2.getFinalPrice());
                    if (data1 < data2) {
                        bean1.setGotGold(gotGold);
                        bean1.setCouponAmount(couponAmount);
                        return  bean1;
                    } else {
                        bean2.setGotGold(gotGold);
                        bean2.setCouponAmount(couponAmount);
                        return bean2;
                    }
                } else {
                    return beans.get(0);
                }
            }
        }
        return null;
    }

    @Override
    public int selectGotNum(int activityId, String someday) {
        if (activityId > 0) {
            return guessRecordMapper.selectGotNum(activityId, someday);
        }
        return 0;
    }

    @Override
    public GuessJoinMember findJoinInfo(String memberId, int activityId) {
        if (StringUtils.isNotBlank(memberId) && activityId > 0) {
            return guessJoinMemberMapper.findJoinInfo(memberId, activityId);
        }
        return null;
    }

    @Override
    public boolean saveRecord(GuessRecord record) {
        if (record != null) {
            GuessJoinMember joinMember = guessJoinMemberMapper.findJoinInfo(record.getMemberId(), record.getActivityId());
            if (joinMember == null) {
                joinMember = new GuessJoinMember();
                joinMember.setActivityId(record.getActivityId());
                joinMember.setAddTime(UF.getFormatDateTime(LocalDateTime.now()));
                joinMember.setJoinNum(1);
                joinMember.setLastestTime(UF.getFormatDateTime(LocalDateTime.now()));
                joinMember.setMemberId(record.getMemberId());
                int rows = guessJoinMemberMapper.insert(joinMember);
                if (rows > 0) {
                    return guessRecordMapper.insert(record) > 0 ? true : false;
                }
            } else {
                if (joinMember.getBalance() > 0) {
                    int rows = guessJoinMemberMapper.updateBalance(record.getMemberId(), record.getActivityId(), -1);
                    if (rows > 0) {
                        guessJoinMemberMapper.updateJoinInfo(record.getMemberId(), record.getActivityId(), UF.getFormatDateTime(LocalDateTime.now()));
                        return guessRecordMapper.insert(record) > 0 ? true : false;
                    }
                }
            }
        }
        return false;
    }

    @Override
    public GuessRecord findById(int id) {
        if (id > 0) {
            return guessRecordMapper.findById(id);
        }
        return null;
    }

    @Override
    public boolean updateFinalPrice(int activityId, double finalPrice) {
        if (activityId > 0 && finalPrice > 0) {
            return guessRecordMapper.updateFinalPrice(activityId, finalPrice) > 0 ? true : false;
        }
        return false;
    }

    @Override
    public boolean updateGotRecord(int activityId) {
        if (activityId > 0) {
            return guessRecordMapper.updateGotRecord(activityId) > 0 ? true : false;
        }
        return false;
    }

    @Override
    public boolean updateFailedRecord(int activityId) {
        if (activityId > 0) {
            return guessRecordMapper.updateFailedRecord(activityId) > 0 ? true : false;
        }
        return false;
    }

}
